package cn.lngaosu.lwyd.module.integration.service.weixinuseranalysis;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.lngaosu.lwyd.framework.common.util.http.HttpUtils;
import cn.lngaosu.lwyd.module.infra.service.config.ConfigService;
import cn.lngaosu.lwyd.module.integration.service.apptoken.AppTokenService;
import cn.lngaosu.lwyd.module.integration.service.weixinarticle.WeixinArticleServiceImpl;
import cn.lngaosu.lwyd.module.system.dal.dataobject.webinterfacelog.WebinterfaceLogDO;
import cn.lngaosu.lwyd.module.system.dal.mysql.webinterfacelog.WebinterfaceLogMapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import cn.lngaosu.lwyd.module.integration.controller.admin.weixinuseranalysis.vo.*;
import cn.lngaosu.lwyd.module.integration.dal.dataobject.weixinuseranalysis.WeixinUserAnalysisDO;
import cn.lngaosu.lwyd.module.integration.dal.dataobject.weixinuseranalysis.WeixinUserSummaryDO;
import cn.lngaosu.lwyd.framework.common.pojo.PageResult;
import cn.lngaosu.lwyd.framework.common.pojo.PageParam;
import cn.lngaosu.lwyd.framework.common.util.object.BeanUtils;

import cn.lngaosu.lwyd.module.integration.dal.mysql.weixinuseranalysis.WeixinUserAnalysisMapper;
import cn.lngaosu.lwyd.module.integration.dal.mysql.weixinuseranalysis.WeixinUserSummaryMapper;

import static cn.lngaosu.lwyd.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.lngaosu.lwyd.framework.common.util.collection.CollectionUtils.convertList;
import static cn.lngaosu.lwyd.framework.common.util.collection.CollectionUtils.diffList;
import static cn.lngaosu.lwyd.module.integration.enums.ErrorCodeConstants.*;

/**
 * 微信用户分析表(增减合计、总用户量) Service 实现类
 *
 * @author 张恒
 */
@Service
@Validated
public class WeixinUserAnalysisServiceImpl implements WeixinUserAnalysisService {
    private static final Logger logger = LoggerFactory.getLogger(WeixinUserAnalysisServiceImpl.class);

    @Resource
    private WeixinUserAnalysisMapper weixinUserAnalysisMapper;
    @Resource
    private WeixinUserSummaryMapper weixinUserSummaryMapper;
    @Resource
    private AppTokenService appTokenService;
    @Resource
    private ConfigService configService;
    @Resource
    private WebinterfaceLogMapper webinterfaceLogMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createWeixinUserAnalysis(WeixinUserAnalysisSaveReqVO createReqVO) {
        // 插入
        WeixinUserAnalysisDO weixinUserAnalysis = BeanUtils.toBean(createReqVO, WeixinUserAnalysisDO.class);
        weixinUserAnalysisMapper.insert(weixinUserAnalysis);

        // 插入子表
        createWeixinUserSummaryList(weixinUserAnalysis.getId(), createReqVO.getWeixinUserSummarys());
        // 返回
        return weixinUserAnalysis.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateWeixinUserAnalysis(WeixinUserAnalysisSaveReqVO updateReqVO) {
        // 校验存在
        validateWeixinUserAnalysisExists(updateReqVO.getId());
        // 更新
        WeixinUserAnalysisDO updateObj = BeanUtils.toBean(updateReqVO, WeixinUserAnalysisDO.class);
        weixinUserAnalysisMapper.updateById(updateObj);

        // 更新子表
        updateWeixinUserSummaryList(updateReqVO.getId(), updateReqVO.getWeixinUserSummarys());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteWeixinUserAnalysis(Long id) {
        // 校验存在
        validateWeixinUserAnalysisExists(id);
        // 删除
        weixinUserAnalysisMapper.deleteById(id);

        // 删除子表
        deleteWeixinUserSummaryByAnalysisId(id);
    }

    @Override
        @Transactional(rollbackFor = Exception.class)
    public void deleteWeixinUserAnalysisListByIds(List<Long> ids) {
        // 校验存在
        validateWeixinUserAnalysisExists(ids);
        // 删除
        weixinUserAnalysisMapper.deleteByIds(ids);
    
    // 删除子表
            deleteWeixinUserSummaryByAnalysisIds(ids);
    }

    private void validateWeixinUserAnalysisExists(List<Long> ids) {
        List<WeixinUserAnalysisDO> list = weixinUserAnalysisMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(WEIXIN_USER_ANALYSIS_NOT_EXISTS);
        }
    }

    private void validateWeixinUserAnalysisExists(Long id) {
        if (weixinUserAnalysisMapper.selectById(id) == null) {
            throw exception(WEIXIN_USER_ANALYSIS_NOT_EXISTS);
        }
    }

    @Override
    public WeixinUserAnalysisDO getWeixinUserAnalysis(Long id) {
        return weixinUserAnalysisMapper.selectById(id);
    }

    @Override
    public PageResult<WeixinUserAnalysisDO> getWeixinUserAnalysisPage(WeixinUserAnalysisPageReqVO pageReqVO) {
        return weixinUserAnalysisMapper.selectPage(pageReqVO);
    }

    // ==================== 子表（微信用户增减数据） ====================

    @Override
    public List<WeixinUserSummaryDO> getWeixinUserSummaryListByAnalysisId(Long analysisId) {
        return weixinUserSummaryMapper.selectListByAnalysisId(analysisId);
    }

    @Override
    public void syncWeixinUserAnalysis() {
        // 获取微信token
        String weixinToken = appTokenService.getWeixinToken();
        if (StringUtils.isEmpty(weixinToken)) {
            throw exception(WEIXIN_TOKEN_NOT_EXISTS);
        }

        // 接口配置
        String configValue = configService.getConfigValueByKey("weixinConfig");
        if (StringUtils.isEmpty(configValue)) {
            throw exception(INTERFACE_CONFIG_NOT_EXISTS);
        }

        JSONObject configJo = JSONObject.parseObject(configValue);
        // 接口开关
        String onOff = configJo.getString("onOff");
        if (!"on".equals(onOff)) {
            throw exception(INTERFACE_CONFIG_NOT_EXISTS);
        }

        // 获取用户增减数据地址
        String userSummaryUrl = configJo.getString("userSummaryUrl");
        userSummaryUrl = userSummaryUrl + "?access_token=" + weixinToken;
        // 获取累计用户数据地址
        String userCumulateUrl = configJo.getString("userCumulateUrl");
        userCumulateUrl = userCumulateUrl + "?access_token=" + weixinToken;

        // 构造请求参数（每天查询一次，默认查询前一天数据）
        LocalDate date = LocalDate.now().minusDays(1L);
        JSONObject params = new JSONObject();
        params.put("begin_date", date.toString());
        params.put("end_date", date.toString());

        WebinterfaceLogDO webinterfaceLogDO = new WebinterfaceLogDO();
        WebinterfaceLogDO webinterfaceLogDO1 = new WebinterfaceLogDO();
        try {
            // 初始化用户增减接口日志数据（默认成功）
            webinterfaceLogDO.setInterfaceSystemName("微信公众号");
            webinterfaceLogDO.setInterfaceName("获取用户增减数据");
            webinterfaceLogDO.setInterfaceUrl(userSummaryUrl);
            webinterfaceLogDO.setInterfaceRequestMethod("POST");
            webinterfaceLogDO.setInterfaceParam(JSONObject.toJSONString(params));
            webinterfaceLogDO.setInterfaceStatus("成功");
            webinterfaceLogMapper.insert(webinterfaceLogDO);

            // 获取用户增减数据
            String userSummaryResult = HttpUtils.post(userSummaryUrl, new HashMap<>(), JSONObject.toJSONString(params));
            // 解析接口结果
            JSONObject userSummaryResultJo = JSONObject.parseObject(userSummaryResult);
            Integer userSummaryErrcode = userSummaryResultJo.getInteger("errcode");
            if (ObjectUtils.isNotEmpty(userSummaryErrcode)) {
                webinterfaceLogDO.setInterfaceStatus("失败");
                webinterfaceLogDO.setInterfaceErrorInfo(userSummaryResult);
                webinterfaceLogMapper.updateById(webinterfaceLogDO);
                return;
            }
            webinterfaceLogDO.setInterfaceErrorInfo(userSummaryResult);
            webinterfaceLogMapper.updateById(webinterfaceLogDO);


            // 初始化用户增减接口日志数据（默认成功）
            webinterfaceLogDO1.setInterfaceSystemName("微信公众号");
            webinterfaceLogDO1.setInterfaceName("获取累计用户数据");
            webinterfaceLogDO1.setInterfaceUrl(userCumulateUrl);
            webinterfaceLogDO1.setInterfaceRequestMethod("POST");
            webinterfaceLogDO1.setInterfaceParam(JSONObject.toJSONString(params));
            webinterfaceLogDO1.setInterfaceStatus("成功");
            webinterfaceLogMapper.insert(webinterfaceLogDO1);

            // 获取累计用户数据
            String userCumulateResult = HttpUtils.post(userCumulateUrl, new HashMap<>(), JSONObject.toJSONString(params));
            // 解析接口结果
            JSONObject userCumulateResultJo = JSONObject.parseObject(userCumulateResult);
            Integer userCumulateErrcode = userCumulateResultJo.getInteger("errcode");
            if (ObjectUtils.isNotEmpty(userCumulateErrcode)) {
                webinterfaceLogDO1.setInterfaceStatus("失败");
                webinterfaceLogDO1.setInterfaceErrorInfo(userCumulateResult);
                webinterfaceLogMapper.updateById(webinterfaceLogDO1);
                return;
            }
            webinterfaceLogDO1.setInterfaceErrorInfo(userCumulateResult);
            webinterfaceLogMapper.updateById(webinterfaceLogDO1);

            // 处理接口数据
            // 子表
            JSONArray userSummaryJa = userSummaryResultJo.getJSONArray("list");
            List<WeixinUserSummaryDO> weixinUserSummaryDOS = BeanUtils.toBean(userSummaryJa, WeixinUserSummaryDO.class);
            // 主表
            JSONArray userCumulateJa = userCumulateResultJo.getJSONArray("list");
            JSONObject userCumulateJo = userCumulateJa.getJSONObject(0);
            WeixinUserAnalysisSaveReqVO saveReqVO = BeanUtils.toBean(userCumulateJo, WeixinUserAnalysisSaveReqVO.class);

            int newUser = 0;
            int cancelUser = 0;
            if (CollectionUtils.isNotEmpty(weixinUserSummaryDOS)) {
                newUser = weixinUserSummaryDOS.stream().filter(o -> ObjectUtils.isNotEmpty(o.getNewUser()))
                        .map(WeixinUserSummaryDO::getNewUser).reduce(0, Integer::sum);
                cancelUser = weixinUserSummaryDOS.stream().filter(o -> ObjectUtils.isNotEmpty(o.getCancelUser()))
                        .map(WeixinUserSummaryDO::getCancelUser).reduce(0, Integer::sum);
            }
            saveReqVO.setNewUser(newUser);
            saveReqVO.setCancelUser(cancelUser);
            saveReqVO.setWeixinUserSummarys(weixinUserSummaryDOS);

            // 查询本地是否有这天的数据，如果有则更新
            LambdaQueryWrapper<WeixinUserAnalysisDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WeixinUserAnalysisDO::getRefDate, saveReqVO.getRefDate());
            List<WeixinUserAnalysisDO> weixinUserAnalysisDOS = weixinUserAnalysisMapper.selectList(queryWrapper);
            if (CollectionUtils.isNotEmpty(weixinUserAnalysisDOS)) {
                saveReqVO.setId(weixinUserAnalysisDOS.get(0).getId());
                updateWeixinUserAnalysis(saveReqVO);
            } else {
                createWeixinUserAnalysis(saveReqVO);
            }
        } catch (Exception e) {
            webinterfaceLogDO.setInterfaceStatus("失败");
            webinterfaceLogDO.setInterfaceErrorInfo(e.getMessage());
            webinterfaceLogMapper.updateById(webinterfaceLogDO);
            logger.error("微信公众号【获取用户增减数据、获取累计用户数据】接口失败！", e);
        }
    }

    private void createWeixinUserSummaryList(Long analysisId, List<WeixinUserSummaryDO> list) {
        list.forEach(o -> o.setAnalysisId(analysisId).clean());
        weixinUserSummaryMapper.insertBatch(list);
    }

    private void updateWeixinUserSummaryList(Long analysisId, List<WeixinUserSummaryDO> list) {
	    list.forEach(o -> o.setAnalysisId(analysisId).clean());
	    List<WeixinUserSummaryDO> oldList = weixinUserSummaryMapper.selectListByAnalysisId(analysisId);
	    List<List<WeixinUserSummaryDO>> diffList = diffList(oldList, list, (oldVal, newVal) -> {
            boolean same = ObjectUtil.equal(oldVal.getId(), newVal.getId());
            if (same) {
                newVal.setId(oldVal.getId()).clean(); // 解决更新情况下：updateTime 不更新
            }
            return same;
	    });

	    // 第二步，批量添加、修改、删除
	    if (CollUtil.isNotEmpty(diffList.get(0))) {
	        weixinUserSummaryMapper.insertBatch(diffList.get(0));
	    }
	    if (CollUtil.isNotEmpty(diffList.get(1))) {
	        weixinUserSummaryMapper.updateBatch(diffList.get(1));
	    }
	    if (CollUtil.isNotEmpty(diffList.get(2))) {
	        weixinUserSummaryMapper.deleteByIds(convertList(diffList.get(2), WeixinUserSummaryDO::getId));
	    }
    }

    private void deleteWeixinUserSummaryByAnalysisId(Long analysisId) {
        weixinUserSummaryMapper.deleteByAnalysisId(analysisId);
    }

	private void deleteWeixinUserSummaryByAnalysisIds(List<Long> analysisIds) {
        weixinUserSummaryMapper.deleteByAnalysisIds(analysisIds);
	}

}